package com.studiocode.aspeaker;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import com.android.internal.telephony.ITelephony;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
import android.telephony.SmsMessage;
import android.telephony.TelephonyManager;
import android.util.Log;

public class aSpeakerService extends Service
{
    private NotificationManager mNotificationManager;
    private Notification notification;
    private int ASPEAKER_ID = 1;
    
	private TelephonyManager m_telephonyManager;
	private ITelephony m_telephonyService;
	private PhoneStateListener m_phoneStateListener;
	private AudioManager m_audioManager;
	private MyPhoneStateListener phoneListener;

	private boolean CanSpeak = true;
	private boolean SpeakSMS = true;
	private boolean SpeakOnlyRingMode = true;
	private BroadcastReceiverSrv my_intent_srv;
	
	//tratto da: http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/ForegroundService.html
	private static final Class[] mStartForegroundSignature = new Class[] {
		int.class, Notification.class};
	private static final Class[] mStopForegroundSignature = new Class[] {
		boolean.class};
	
    private Method mStartForeground;
    private Method mStopForeground;
    private Object[] mStartForegroundArgs = new Object[2];
    private Object[] mStopForegroundArgs = new Object[1];
    
	@Override
	public void onCreate()
	{
		// TODO Auto-generated method stub
		super.onCreate();
		
		try
		{
			mStartForeground = getClass().getMethod("startForeground"
					,mStartForegroundSignature);
			//mStopForeground = getClass().getMethod("stopForeground",mStopForegroundSignature);
		}
		catch (NoSuchMethodException e)
		{
			// Running on an older platform.
			mStartForeground = mStopForeground = null;
		}
		
		// Get the notification manager service.
        mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        PutNotification();
        //notification.defaults |= Notification.DEFAULT_VIBRATE;  //Vibra
        //mNotificationManager.notify(ASPEAKER_ID, notification);
        
        
        
        // register broadcast receiver 
        IntentFilter filterLoc = new IntentFilter(Global.A_TO_S_BROADCAST_SRV); 
        my_intent_srv = new BroadcastReceiverSrv(); 
        registerReceiver(my_intent_srv, filterLoc);
	}
	
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) 
	{
		// TODO Auto-generated method stub
        
		Log.v(Global.TAGDEBUG, "aSpeaker service partito!");
		
		startForegroundCompat(ASPEAKER_ID, notification);
		
        m_audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        
        //Parte che risponde alle chiamate
         m_telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);

         Class c = null;
  		try {
  			c = Class.forName(m_telephonyManager.getClass().getName());
  		} catch (ClassNotFoundException e) {
  			// TODO Auto-generated catch block
  			e.printStackTrace();
  		}
          Method m = null;
  		try {
  			m = c.getDeclaredMethod("getITelephony");
  		} catch (SecurityException e) {
  			// TODO Auto-generated catch block
  			e.printStackTrace();
  		} catch (NoSuchMethodException e) {
  			// TODO Auto-generated catch block
  			e.printStackTrace();
  		}
          m.setAccessible(true);
          try {
  			m_telephonyService = (ITelephony)m.invoke(m_telephonyManager);
  		} catch (IllegalArgumentException e) {
  			// TODO Auto-generated catch block
  			Log.v(Global.TAGDEBUG, "Errore: " + e.getMessage().toString());
  		} catch (IllegalAccessException e) {
  			// TODO Auto-generated catch block
  			Log.v(Global.TAGDEBUG, "Errore: " + e.getMessage().toString());
  		} catch (InvocationTargetException e) {
  			// TODO Auto-generated catch block
  			Log.v(Global.TAGDEBUG, "Errore: " + e.getMessage().toString());
  		}
  		catch (Exception e)
  		{
  			Log.v(Global.TAGDEBUG, "Errore: " + e.getMessage().toString());
  		}

  		phoneListener = new MyPhoneStateListener(this.getApplicationContext(),
  				m_audioManager,m_telephonyService);
  		phoneListener.setCanSpeak(CanSpeak);
  		phoneListener.setSpeakOnlyRingMode(SpeakOnlyRingMode);
  		
      	//Istanzio i broadcast receivers
      	registerReceiver(IncomingCall, new IntentFilter(Global.INCOMING_CALL_ACTION));
      	registerReceiver(IncomingSMS,  new IntentFilter(Global.INCOMING_SMS));
      	
      	//return super.onStartCommand(intent, flags, startId);
		return START_STICKY;
	}

	@Override
	public void onDestroy()
	{
		// TODO Auto-generated method stub
		stopForegroundCompat(ASPEAKER_ID);
		unregisterReceiver(IncomingCall);
		unregisterReceiver(IncomingSMS);
		unregisterReceiver(my_intent_srv);
		Log.v(Global.TAGDEBUG, "aSpeaker service chiuso!");
		super.onDestroy();
	}
	
	@Override
	public IBinder onBind(Intent arg0)
	{
		// TODO Auto-generated method stub
		return null;
	}

	//Broadcast receiver per preferenze
    public class BroadcastReceiverSrv extends BroadcastReceiver
    { 
        @Override 
        public void onReceive(Context context, Intent intent)
        { 
            //Riceve il cambio di preferenze
            if (intent.getAction().equals(Global.A_TO_S_BROADCAST_SRV))
            {
                try
                {
                	Log.v(Global.TAGDEBUG, "Ricevuto intent!");
                	boolean oldCanSpeak = CanSpeak;
                	CanSpeak = intent.getExtras().getBoolean(Global.CAN_SPEAK);
                	SpeakSMS = intent.getExtras().getBoolean(Global.SPEAK_SMS);
                	SpeakOnlyRingMode = intent.getExtras().getBoolean(Global.SPEAK_ONLY_RING_MODE);
                	
              		phoneListener.setCanSpeak(CanSpeak);
              		phoneListener.setSpeakOnlyRingMode(SpeakOnlyRingMode);
              		
              		if (oldCanSpeak != CanSpeak)
              		{
              			PutNotification();
              			mNotificationManager.notify(ASPEAKER_ID, notification);
              		}
                }
                catch (Exception ex)
                {
                	Log.v(Global.TAGDEBUG, "Errore BroadcastReceiverSrv: " + ex.getMessage().toString());
                }
            }
        }
         
    }
    
	//Broadcast receiver per chiamate in arrivo  
    public final BroadcastReceiver IncomingCall = new BroadcastReceiver()
    {   
		@Override
		public void onReceive(Context context, Intent intent) {
			// TODO Auto-generated method stub
		    m_telephonyManager.listen(phoneListener, PhoneStateListener.LISTEN_CALL_STATE);		    
		}
    };
       
    //Broadcast receiver per sms in arrivo
    public final BroadcastReceiver IncomingSMS = new BroadcastReceiver()
    {   
		@Override
		public void onReceive(Context context, Intent intent)
		{
			// TODO Auto-generated method stub
			if (intent.getAction().equals(Global.INCOMING_SMS))
			{  
				Bundle bundle = intent.getExtras(); 
				SmsMessage[ ] msgs = null; 
				String strSmsDa = "";
				String strSmsBody = "";
				if (bundle != null) 
				{ 
					//---retrieve the received message here --- 
					Object[ ] pdus = (Object[ ]) bundle.get("pdus"); 
					msgs = new SmsMessage[pdus.length]; 
					for (int i=0; i<msgs.length; i++)
					{ 
						msgs[i] = SmsMessage.createFromPdu((byte[ ])pdus[i]);
						strSmsDa += msgs[i].getOriginatingAddress();
				    	ContactsUtils myCU = new ContactsUtils();
				    	strSmsDa = myCU.NameFromNumber(context, strSmsDa);
						strSmsBody += msgs[i].getMessageBody().toString(); 
						
					    Log.v(Global.TAGDEBUG, "Nuovo SMS da " + strSmsDa);
					    String Testo = "";
					    if (SpeakSMS)
					    {
					    	Testo = getString(R.string.speakNuovoSmsDa) + 
					    	strSmsDa + ". " + getString(R.string.speakOggetto) + strSmsBody;
					    }
					    else
					    	Testo = getString(R.string.speakNuovoSmsDa) + strSmsDa + ".";

					    if ((m_audioManager.getRingerMode() == AudioManager.RINGER_MODE_NORMAL) ||
					    		(SpeakOnlyRingMode == false))
					    {
					    	TTS myTTS2 = new TTS(context,Testo, CanSpeak);
					    }
					}
				}
			}
		}
    };
    
    
    /**     * This is a wrapper around the new startForeground method, using the older
     *      * APIs if it is not available.
     *           */
    void startForegroundCompat(int id, Notification notification)
    {
    	// If we have the new startForeground API, then use it.
    	if (mStartForeground != null)
    	{
    		mStartForegroundArgs[0] = Integer.valueOf(id);
    		mStartForegroundArgs[1] = notification;
    		try
    		{                
    			mStartForeground.invoke(this, mStartForegroundArgs);
    		}
    		catch (InvocationTargetException e)
    		{
				// Should not happen.
				Log.w(Global.TAGDEBUG, "Unable to invoke startForeground", e);
			}
    		catch (IllegalAccessException e)
    		{
				// Should not happen.
				Log.w(Global.TAGDEBUG, "Unable to invoke startForeground", e);
			}
			return;
		}
    	// Fall back on the old API.
    	setForeground(true);
    	mNotificationManager.notify(id, notification);
    }
    
    /*** This is a wrapper around the new stopForeground method, using the older   
     *      APIs if it is not available.     
     */
    void stopForegroundCompat(int id)
    {
    	// If we have the new stopForeground API, then use it.
    	if (mStopForeground != null)
    	{
    		mStopForegroundArgs[0] = Boolean.TRUE;
    		try
    		{
    			mStopForeground.invoke(this, mStopForegroundArgs);
    		}
    		catch (InvocationTargetException e)
    		{
    				// Should not happen.
    				Log.w(Global.TAGDEBUG, "Unable to invoke stopForeground", e);
    		}
    		catch (IllegalAccessException e)
    		{
				// Should not happen.
				Log.w(Global.TAGDEBUG, "Unable to invoke stopForeground", e);
			}
			return;
			}
    	// Fall back on the old API.  Note to cancel BEFORE changing the
    	// foreground state, since we could be killed at that point.
    	mNotificationManager.cancel(id);
    	setForeground(false);
    }

    private void PutNotification()
    {
        int icon = R.drawable.speaker;
        CharSequence tickerText = "";
        CharSequence contentText = "";
        if (CanSpeak)
        {
	        tickerText = this.getString(R.string.aspeakerOn);
	        contentText = this.getString(R.string.aspeakerOn);
        }
        else
        {
	        tickerText = this.getString(R.string.aspeakerOff);
	        contentText = this.getString(R.string.aspeakerOff);	
        }
        long when = System.currentTimeMillis();
        notification = new Notification(icon, tickerText, when);
        Context context = getApplicationContext();
        CharSequence contentTitle = "aSpeaker";
        
        Intent notificationIntent = new Intent(this, frmMain.class);
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
        notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
        notification.defaults |= Notification.DEFAULT_SOUND;    //Suona
        notification.defaults |= Notification.DEFAULT_LIGHTS;   //LED
        notification.flags |= Notification.FLAG_ONGOING_EVENT;
    }
}
